#include "MultiLineChart.hpp"
#include "cairomm/refptr.h"
#include "pangomm/fontdescription.h"
#include <stdexcept>
#include <random>
#include <gtkmm/widget.h>
#include <string>

glMultiLineChart::glMultiLineChart(float maxval_,float minval_,int points,int lines)
{
  if(maxval_<minval_)
    throw std::logic_error("maxval less of minval");
  if(points<2)
    throw std::logic_error("display points is too less");
  if(lines<1)
    throw std::logic_error("lines is too less");
  minval=minval_;
  maxval=maxval_;
  allpoints=points;
  oriData.resize(lines);
  for(auto i : oriData)
    i.resize(points,0);
  LineColorTable.resize(lines);
  std::random_device radDevice;
  std::mt19937 gen(radDevice());
std::uniform_int_distribution<> distrib(0,255);
  for(auto & i : LineColorTable)
  {
    std::get<0>(i)=distrib(gen);
    std::get<1>(i)=distrib(gen);
    std::get<2>(i)=distrib(gen);
  }
}

glMultiLineChart::~glMultiLineChart()
{

}


void glMultiLineChart::ClearFrameCounter()
{
  frameCounter=0;
}

void glMultiLineChart::DrawCall(const Cairo::RefPtr<Cairo::Context>& cr,int width,int height,Gtk::Widget* widget)
{
  //绘制坐标系
  cr->save();
  int SourcePointX=20;
  int SourcePointY=height-20;
  cr->set_source_rgb(255,255,255);
  cr->set_line_width(3);
  cr->move_to(SourcePointX,SourcePointY);
  cr->line_to(20, 20);
  cr->line_to(15, 25);
  cr->move_to(20, 20);
  cr->line_to(25, 25);
  cr->move_to(SourcePointX, SourcePointY);
  cr->line_to(width-20, height-20);
  cr->line_to(width-25, height-25);
  cr->move_to(width-20, height-20);
  cr->line_to(width-25, height-15);
  cr->stroke();
  cr->restore();

  //绘制折线 空间x:25 ~ width-25 y:25 ~ height-25
  cr->save();
  float scale_item=(height-50)/(maxval-minval);
  int increase_val=(width-50)/(allpoints-1);
  // for(const auto & i : oriData)
  for(int i=0;i<oriData.size();i++)
  {
    //第一个点要移动过去
    cr->move_to(25, height-25-oriData[i][0]*scale_item);
    cr->set_source_rgb(
      std::get<0>(LineColorTable[i]),
      std::get<1>(LineColorTable[i]),
      std::get<2>(LineColorTable[i])
    );
    for(int j=1;j<allpoints;j++)
    {
      cr->line_to(25+j*increase_val, height-25-oriData[i][j]*scale_item);
    }
    cr->stroke();
  }
  cr->restore();
  cr->save();
  cr->set_source_rgb(255, 255, 255);
  for(int j=0;j<allpoints;j++)
    DrawFont(cr, std::to_string(frameCounter>j ? frameCounter-j : 0), 25+j*increase_val, height-10, widget);
  //计算垂直标签
  int ylab_increate=(height-50)/5;
  for(int j=0;j<=5;j++)
    DrawFont(cr, std::to_string((int)(minval+(maxval-minval)/5*j)), 10, height-25-j*ylab_increate,widget);
  cr->restore();
}

void glMultiLineChart::InputData(float points,int index)
{
  oriData[index].push_front(points);
  oriData[index].pop_back();
  frameCounter++;
}

void glMultiLineChart::DrawFont(const Cairo::RefPtr<Cairo::Context>& cr,std::string str,int x,int y,Gtk::Widget* widget)
{
  Pango::FontDescription font;
  font.set_family("Monospace");
  auto layout = widget->create_pango_layout(str);
  layout->set_font_description(font);

  int text_width;
  int text_height;

  //get the text dimensions (it updates the variables -- by reference)
  layout->get_pixel_size(text_width, text_height);

  // Position the text in the middle
  cr->move_to(x-text_width/2, y-text_height/2);

  layout->show_in_cairo_context(cr);
}
